package com.奇技淫巧;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSA非对称加密Util {

    public static void main(String[] args) throws Exception {
        //生成RSA密钥对
        KeyPair keyPair = generateRSAKeyPair();
        PublicKey publicKey = getPublicKey(keyPair);
        PrivateKey privateKey = getPrivateKey(keyPair);

        // 签名
        Signature verifier = Signature.getInstance("SHA256withRSA");
        verifier.initSign(privateKey);
        verifier.update("Hello, RSA!!".getBytes());
        byte[] signature = verifier.sign();

        // 验证签名
        verifier.initVerify(publicKey);
        verifier.update("Hello, RSA!!".getBytes());
        boolean isVerified = verifier.verify(signature);
        System.out.println("签名验证结果: " + isVerified);
    }
    // 解密
    public static byte[] decrypt(byte[] encryptedData, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(encryptedData);
    }
    // 加密
    public static byte[] encrypt(byte[] data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }
    //生成RSA密钥对
    public static KeyPair generateRSAKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);//随机数生成，初始化大小
        return keyPairGenerator.generateKeyPair();
    }
    // 从密钥对中获取公钥
    public static PublicKey getPublicKey(KeyPair keyPair) {
        return keyPair.getPublic();
    }
    // 从密钥对中获取私钥
    public static PrivateKey getPrivateKey(KeyPair keyPair) {
        return keyPair.getPrivate();
    }

    // 从公钥中获取公钥编码
    public static byte[] getPublicKeyEncoded(PublicKey publicKey) {
        return publicKey.getEncoded();
    }
    // 从私钥中获取私钥编码
    public static byte[] getPrivateKeyEncoded(PrivateKey privateKey) {
        return privateKey.getEncoded();
    }
    //从公钥编码中获取公钥
    public static PublicKey getPublicKeyFromEncoded(byte[] publicKeyEncoded) {
        try{
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyEncoded);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(x509EncodedKeySpec);
        }catch (Exception e){
            throw new RuntimeException("获取公钥失败", e);
        }
    }
    //从私钥编码中获取私钥
    public static PrivateKey getPrivateKeyFromEncoded(byte[] privateKeyEncoded) {
        try{
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyEncoded);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        }catch (Exception e){
            throw new RuntimeException("获取私钥失败", e);
        }
    }
    //私钥编码 转化成 私钥字符串
    public static String getPrivateKeyStringFromEncoded(byte[] privateKeyEncoded) {
        return Base64.getEncoder().encodeToString(privateKeyEncoded);
    }
    //公钥编码 转化成 公钥字符串
    public static String getPublicKeyStringFromEncoded(byte[] publicKeyEncoded) {
        return Base64.getEncoder().encodeToString(publicKeyEncoded);
    }

    // 从公钥字符串中获取公钥
    public static PublicKey getPublicKeyFromString(String publicKeyString) {
        try{
            publicKeyString = publicKeyString.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replaceAll("\\s", "");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString)));
        }catch (Exception e){
            throw new RuntimeException("获取公钥失败", e);
        }
    }
    // 从私钥字符串中获取私钥
    public static PrivateKey getPrivateKeyFromString(String privateKeyString) {
        try{
            privateKeyString = privateKeyString.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s", "");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString)));
        }catch (Exception e){
            throw new RuntimeException("获取私钥失败", e);
        }
    }


}
